﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using wpf.exontrol.EXG2ANTTLib;

namespace SampleControls
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        const int COL_TASK_TITLE = 0;
        const int COL_ESTIMATE_HRS = 1;
        const int COL_RESPONSIBLE_NAME = 2;
        const int COL_ALLOCATION_PERCENT = 3;
        const int COL_BASELINE_START = 4;
        const int COL_BASELINE_END = 5;

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Configure();
            LoadDemoData();
        }

        private void Configure()
        {
            Column c;
            c = exg2antt1.Columns.Add("Task");
            c.Width = 400;

            c = exg2antt1.Columns.Add("Estimated hrs");
            c.Width = 50;

            c = exg2antt1.Columns.Add("Responsible");
            c.Width = 150;

            c = exg2antt1.Columns.Add("Allocation %");
            c.Width = 50;
            
            c = exg2antt1.Columns.Add("Baseline start");
            c.Width = 90;
            
            c = exg2antt1.Columns.Add("Baseline end");
            c.Width = 90;

            exg2antt1.SingleSel = false;
            //exg2antt1.DblClick += new exg2antt.DblClickEventHandler(exg2antt1_DblClick);
            //exg2antt1.MouseUpEvent += new exg2antt.MouseUpEventHandler(exg2antt1_MouseUpEvent);
            //exg2antt1.KeyDown += new exg2antt.KeyDownEventHandler(exg2antt1_KeyDown);
        }
        /*
        void exg2antt1_KeyDown(object sender, ref short KeyCode, short Shift)
        {
            throw new NotImplementedException();
        }

        void exg2antt1_MouseUpEvent(object sender, short Button, short Shift, int X, int Y)
        {
            if (Button == 2)
            {
                if (exg2antt1.Editing == 0)
                {
                    int c = 0;
                    HitTestInfoEnum hit = HitTestInfoEnum.exHTCell;
                    int i = exg2antt1.get_ItemFromPoint(-1, -1, ref c, ref hit);
                    if (c >= 0)
                    {
                        if (i != 0)
                        {
                            exg2antt1.Items.set_SelectItem(i, true);
                        }

                        contextMenuStrip1.Items.Clear();

                        MenuItem n = new MenuItem();
                        n.Header = "Add New Task";
                        n.Tag = 1;
                        contextMenuStrip1.Items.Add(n);
                        n.Click += new RoutedEventHandler(menuItem_Click);

                        n = new MenuItem();
                        n.Header = "Add a Subtask";
                        n.Tag = 2;
                        contextMenuStrip1.Items.Add(n);
                        n.Click += new RoutedEventHandler(menuItem_Click);

                        if (i != 0)
                        {
                            n = new MenuItem();
                            n.Header = "Remove";
                            n.Tag = 3;
                            contextMenuStrip1.Items.Add(n);
                            n.Click += new RoutedEventHandler(menuItem_Click);
                        }

                        contextMenuStrip1.IsOpen = true;
                    }
                }
            }
        }

        void menuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem m = sender as MenuItem;
            if (m != null)
            {
                switch ((int)m.Tag)
                {
                    case 1:
                        {
                            int i = exg2antt1.Items.AddItem("");
                            exg2antt1.Items.set_SelectItem(i, true);
                            exg2antt1.Edit();
                            break;
                        }
                    case 2:
                        {
                            exg2antt1.LinesAtRoot = wpf.exontrol.EXG2ANTTLib.LinesAtRootEnum.exLinesAtRoot;
                            int i = exg2antt1.Items.InsertItem(exg2antt1.Items.FocusItem, "new task");
                            exg2antt1.Items.set_ExpandItem(exg2antt1.Items.FocusItem, true);
                            exg2antt1.Items.set_SelectItem(i, true);
                            exg2antt1.Edit();
                            break;
                        }
                    case 3:
                        {
                            exg2antt1.Items.RemoveItem(exg2antt1.Items.FocusItem);
                            break;
                        }
                    case 4:
                        {
                            exg2antt1.Edit();
                            break;
                        }
                }
            }
        }

        int editItem = -1, editCol = -1;
        void exg2antt1_DblClick(object sender, short Shift, int X, int Y)
        {
            int colIndex = 0;
            HitTestInfoEnum hitTestInfo = HitTestInfoEnum.exHTCell;
            int hItem = exg2antt1.get_ItemFromPoint(X, Y, ref colIndex, ref hitTestInfo);
            editItem = hItem;
            editCol = colIndex;
            Editor editor = exg2antt1.Items.get_CellEditor(hItem, colIndex);
            if (editor != null)
            {
                switch (colIndex)
                {
                    case COL_TASK_TITLE:
                    case COL_ESTIMATE_HRS: 
                    case COL_RESPONSIBLE_NAME: 
                    case COL_ALLOCATION_PERCENT:
                        editor.EditType = EditTypeEnum.EditType;
                        break;
                    case COL_BASELINE_START: 
                    case COL_BASELINE_END:
                        editor.EditType = EditTypeEnum.DateType;
                        break;
                }
                //exg2antt1.Edit(
            }
        }

        private void exg2antt1_DblClick()
        {
        }
        */

        private void LoadDemoData()
        {
            exg2antt1.BeginUpdate();

            int t1, t2, t3, t4, t5, t6, t7;

            int pInception = AddSummaryTask(0, "Inception", DateTime.Now);
            t1 = AddTask(pInception, "Collect initial requirements", 24, "BA");
            t2 = AddTask(pInception, "Create an outline of functional requirements", 8, "BA", t1);
            t3 = AddTask(pInception, "Conduct req's team review", 8, "Team", t2);
            t4 = AddTask(pInception, "Clarify requirements and finalize the documentation", 24, "BA", t3);
            t5 = AddTask(pInception, "Draft notes about possible ways to architect a system", 24, "Architect", t4);
            AddMilestone(0, "Inception is complete", pInception);

            int pElaboration = AddSummaryTask(0, "Elaboration", null, pInception);
            t1 = AddTask(pElaboration, "Research available 3d party libraries to utilize", 16, "Architect & TL");
            t2 = AddTask(pElaboration, "Document research results", 4, "Architect", t1);
            t3 = AddTask(pElaboration, "Conduct team review of 3d party components", 8, "Team", t2);
            t4 = AddTask(pElaboration, "Work out application architecture", 40, "Architect & TL", t2);
            t5 = AddTask(pElaboration, "Conduct a team review of app architecture", 8, "Team", t3, t4);
            t6 = AddMilestone(0, "Ready for construction start", pElaboration);

            int pConstruction = AddSummaryTask(0, "Construction", null, pElaboration);
            int pFrmwrk = AddSummaryTask(pConstruction, "Framework development", null);
            t1 = AddTask(pFrmwrk, "Implement core sybsystem #1", 16, "Peter Smith");
            t2 = AddTask(pFrmwrk, "Implement core sybsystem #2", 32, "Jim Moorthy");
            t3 = AddTask(pFrmwrk, "Implement core sybsystem #3", 24, "Lee Jourdan");
            t4 = AddTask(pFrmwrk, "Integrate systems into a core framework", 32, "Dev team", t1, t2, t3);

            int pModules = AddSummaryTask(pConstruction, "Modules development", null, pFrmwrk);
            t1 = AddTask(pModules, "Create module #1", 40, "Peter Smith");
            t2 = AddTask(pModules, "Create module #2", 32, "Jim Moorthy");
            t3 = AddTask(pModules, "Create module #3", 16, "Lee Jourdan");
            t4 = AddTask(pModules, "Create module #4", 8, "Peter Smith");
            t5 = AddTask(pModules, "Create module #5", 24, "Lee Jourdan");
            t6 = AddTask(pModules, "Integrate created modules with a framework", 24, "Dev team", t1, t2, t3, t4, t5);

            int pTesting = AddSummaryTask(pConstruction, "Testing", null, pModules);
            t1 = AddTask(pTesting, "Conduct 1st iteration of QA testing", 24, "QA team");
            t2 = AddTask(pTesting, "Bug fixing and performance tuning", 24, "Dev team", t1);
            t3 = AddTask(pTesting, "Conduct 2nd iteration of QA testing", 32, "QA team", t2);
            t4 = AddTask(pTesting, "Bug fixing and performance tuning (of most visible issues)", 16, "Dev team", t3);
            t5 = AddTask(pTesting, "Release  & publish an alpha build", 4, "Build master", t4);
            AddMilestone(0, "Alpha build is released", pConstruction);                
                
            exg2antt1.EndUpdate();
        }
        
        protected int AddSummaryTask(int hParent, string name, DateTime? baselineStart, params int[] hPredecessors) 
        {
            /*
            if (hParent == 0 
                && !baselineStart.HasValue 
                && hPredecessors.Length == 0)
            {
                throw new ApplicationException("Either baseline start date or predecessor task(s) is required");
            }
            */
            if (!baselineStart.HasValue) 
            {
                baselineStart = ComputeBaselineStart(hParent, hPredecessors);
            }
            int hItem = AddTaskRecord(hParent, name, 1, null, baselineStart.Value, hPredecessors);
            exg2antt1.Items.set_CellBold(hItem, 0, true);
            return hItem; 
        }

        protected int AddMilestone(int hParent, string name, params int[] hPredecessors) 
        {
            DateTime date = ComputeBaselineStart(hParent, hPredecessors);
            int hItem = AddTaskRecord(hParent, name, 0, null, date, hPredecessors);
            exg2antt1.Items.set_CellItalic(hItem, 0, true);
            return hItem;
        }

        protected int AddTask(int hParent, string name, int estimateHrs, string responsible, params int[] hPredecessors) 
        {
            DateTime date = ComputeBaselineStart(hParent, hPredecessors);
            return AddTaskRecord(hParent, name, estimateHrs, responsible, date, hPredecessors);
        }

        protected DateTime ComputeBaselineStart(int hParent, params int[] hPredecessors)
        {
            // if hParent is ok and no predeceoors - need to take Parent start date
            // if parent is none - then need to take the end of 'predecessor' tasks
            // all can be summary tasks - so use recursion
            /*
            IList<int> list = new List<int>(hPredecessors);
            list.Add(hParent);
            DateTime value = DateTime.MinValue;
            foreach (int i in list)
            {
                object o = exg2antt1.Items.get_CellData(hParent, COL_BASELINE_END);
                DateTime cellValue = (DateTime)o;
                if (cellValue > value)
                {
                    value = cellValue;
                }
            }
            return value;
            */
            return DateTime.Now; // stub
        }
        
        private int AddTaskRecord(int hParentTask, string name,
            int estimatedHrs, string assigneeName, DateTime? baselineStart, params int[] hPredecessors)
        {
            int hItem = exg2antt1.Items.AddItem(name);
            // check & initialize data
            if (estimatedHrs < 0)
            {
                estimatedHrs = 8; // default is 1 day
            }
            if (!baselineStart.HasValue)
            {
                baselineStart = DateTime.Now;
            }
            DateTime baselineEnd = baselineStart.Value;
            int days = estimatedHrs % 8;
            baselineEnd.AddDays(days);

            // add item
            exg2antt1.Items.set_CellValue(hItem, COL_ESTIMATE_HRS, estimatedHrs);
            exg2antt1.Items.set_CellValue(hItem, COL_RESPONSIBLE_NAME, assigneeName);
            exg2antt1.Items.set_CellValue(hItem, COL_ALLOCATION_PERCENT, 100);
            exg2antt1.Items.set_CellValue(hItem, COL_BASELINE_START, baselineStart.Value.ToShortDateString());
            exg2antt1.Items.set_CellValue(hItem, COL_BASELINE_END, baselineEnd.ToShortDateString());

            if (hParentTask != 0)
            {
                exg2antt1.Items.SetParent(hItem, hParentTask);
            }

            // add bar
            //exg2antt1.Items.AddBar(hItem, assigneeName, baselineStart, baselineEnd);
            
            return hItem;
        }
      

        internal DateTime FromString(string s)
        {
            string delimStr = "//";
            char[] delimiter = delimStr.ToCharArray();
            string[] sA = s.Split(delimiter);
            return new DateTime(int.Parse(sA[2]), int.Parse(sA[0]), int.Parse(sA[1]));
        }
        

    }
}
